package com.ilop.sthome.common;

import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.common.utils.LiveDataBus;
import com.ilop.sthome.common.command.SiterCommand;
import com.ilop.sthome.data.bean.HistoryBean;
import com.ilop.sthome.data.bean.WarnBean;
import com.ilop.sthome.data.enums.CellsEnum;
import com.ilop.sthome.data.enums.SmartDevice;
import com.ilop.sthome.data.event.EventAnswerOK;
import com.ilop.sthome.data.event.EventGatewayInfo;
import com.ilop.sthome.data.event.EventRefreshDevice;
import com.ilop.sthome.data.event.EventRefreshLogs;
import com.ilop.sthome.data.event.EventRefreshScene;
import com.ilop.sthome.data.event.EventRefreshSubLogs;
import com.ilop.sthome.data.event.EventSynchronization;
import com.ilop.sthome.data.greenDao.AutomationBean;
import com.ilop.sthome.data.greenDao.DeviceInfoBean;
import com.ilop.sthome.data.greenDao.RoomBean;
import com.ilop.sthome.utils.CoderUtils;
import com.ilop.sthome.utils.ConfigureUtil;
import com.ilop.sthome.utils.DeviceStatusUtil;
import com.ilop.sthome.utils.greenDao.utils.AutomationDaoUtil;
import com.ilop.sthome.utils.greenDao.utils.DeviceDaoUtil;
import com.ilop.sthome.utils.greenDao.utils.RoomDaoUtil;
import com.ilop.sthome.utils.greenDao.utils.SceneDaoUtil;
import com.siterwell.familywellplus.R;

import java.util.Arrays;
import java.util.List;

/**
 * @author skygge
 * @date 2020/6/11.
 * GitHub：javofxu@github.com
 * email：skygge@yeah.net
 * description：处理所有设备上报数据
 */
public class CommandHandler implements Runnable{
    private static final String TAG = CommandHandler.class.getSimpleName();
    private Context mContext;
    private String mDeviceName;
    private JSONObject mJson;
    private Handler mHandler;

    public CommandHandler(Context context, String deviceName, JSONObject jsonObject, Handler handler) {
        this.mContext = context;
        this.mDeviceName = deviceName;
        this.mJson = jsonObject;
        this.mHandler = handler;
    }

    @Override
    public void run() {
        try {
            String alarmMessage = mJson.getString("alarmMessage");
            if (alarmMessage != null) {
                onAlertPushInfo(alarmMessage, mDeviceName);
                return;
            }
            String fullCode = mJson.toString();
            int cmd = mJson.getIntValue("CMD_CODE");
            String content = mJson.getString("data_str1");
            String content2 = mJson.getString("data_str2");
            switch (cmd){
                case SiterCommand.SEND_ACK://网关应答
                    sendAck(fullCode);
                    break;
                case SiterCommand.UPLOAD_GATEWAY_INFO://上报网关信息
                    getGatewayInfo(mDeviceName, content, content2);
                    break;
                case SiterCommand.UPLOAD_DEVICE_NAME://同步子设备昵称
                    uploadDeviceName(mDeviceName, content2);
                    break;
                case SiterCommand.UPLOAD_DEVICE_STATUS://更新设备状态
                    uploadDeviceStatus(mDeviceName, content, content2);
                    break;
                case SiterCommand.UPLOAD_ALL_DEVICE_STATUS://同步所有子设备
                case SiterCommand.UPLOAD_ALL_DEVICE_STATUS2:
                    uploadAllDeviceStatus(mDeviceName, content, content2);
                    break;
                case SiterCommand.UPLOAD_SCENE_INFO://同步场景信息
                    uploadSceneInfo(mDeviceName, content, content2);
                    break;
                case SiterCommand.UPLOAD_SCENE_AUTO_INFO://同步自动化信息
                    uploadAutoInfo(mDeviceName, content, content2);
                    break;
                case SiterCommand.UPLOAD_CURRENT_SCENE://当前场景
                    uploadCurrentScene(mDeviceName, content);
                    break;
                case SiterCommand.UPLOAD_ALARM_LOGS_INFO://报警推送信息
                    uploadAlarmLogsInfo(mDeviceName, content, content2);
                    break;
                case SiterCommand.UPLOAD_SUB_DEVICE_ALARM_LOGS_INFO://子设备记录
                    uploadSubDeviceAlarmLogsInfo(mDeviceName, content, content2);
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设备上报 设备应答/11帧
     * @param code ok/none
     */
    private void sendAck(String code){
        EventAnswerOK event = JSON.parseObject(code, EventAnswerOK.class);
        mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_ANSWER_OK).setValue(event));
    }

    /**
     * 设备上报 网关信息/13帧
     * @param code 数据
     */
    private void getGatewayInfo(String deviceName, String str1, String code){
        EventGatewayInfo event = new EventGatewayInfo();
        event.setCMD_CODE(13);
        event.setData_str1(str1);
        event.setData_str2(code);
        event.setDeviceName(deviceName);
        mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_GATEWAY_INFO).setValue(event));
    }

    /**
     * 设备上报 同步设备/55帧
     * @param deviceName 网关
     * @param content data_str1
     * @param content2 data_str2
     * 各32各设备
     */
    private void uploadAllDeviceStatus(String deviceName, String content, String content2){
        try{
            if (!TextUtils.isEmpty(content) && content.length()>=14){
                int deviceNum = content.length()/14;
                for (int i = 0; i < deviceNum; i++) {
                    String code = content.substring(i*14, (i+1)*14);
                    int deviceId = Integer.parseInt(code.substring(0, 2), 16);
                    String deviceType = code.substring(2, 6);
                    String singleHex = "0"+ code.substring(6, 7);
                    String roomHex = "0"+ code.substring(7, 8);
                    String deviceStatus = code.substring(10);
                    if ("0000".equals(deviceStatus)){
                        DeviceDaoUtil.getInstance().deleteByDeviceName(deviceName, deviceId);
                    }else {
                        String quantity = code.substring(8, 10);
                        String status = singleHex + quantity + deviceStatus;
                        DeviceDaoUtil.getInstance().updateSubDevice(deviceName, deviceId, deviceType, status, roomHex);
                    }
                }
            }
            if (!TextUtils.isEmpty(content2) && content2.length()>=14){
                int deviceNum = content2.length()/14;
                for (int i = 0; i < deviceNum; i++) {
                    String code = content2.substring(i*14, (i+1)*14);
                    int deviceId = Integer.parseInt(code.substring(0, 2), 16);
                    String deviceType = code.substring(2, 6);
                    String singleHex = "0"+ code.substring(6, 7);
                    String roomHex = "0"+ code.substring(7, 8);
                    String deviceStatus = code.substring(10);
                    if ("0000".equals(deviceStatus)){
                        DeviceDaoUtil.getInstance().deleteByDeviceName(deviceName, deviceId);
                    }else {
                        String quantity = code.substring(8, 10);
                        String status = singleHex + quantity + deviceStatus;
                        DeviceDaoUtil.getInstance().updateSubDevice(deviceName, deviceId, deviceType, status, roomHex);
                    }
                }
            }
            EventSynchronization event = new EventSynchronization();
            event.setState(EventSynchronization.SYN_DEVICE);
            event.setDeviceName(deviceName);
            mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_SYNCHRONIZATION).setValue(event));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 设备上报 更新设备状态/19帧
     * @param deviceName 网关
     * @param content data_str1
     * @param status data_str2
     * 返回syncOVER(结束帧)时候表示子设备同步完成
     */
    private void uploadDeviceStatus(String deviceName, String content, String status){
        int deviceId = Integer.parseInt(content.substring(0, 4), 16);
        String device_type = content.substring(4, 8);
        if ("syncOVER".equals(status)) {
            EventSynchronization event = new EventSynchronization();
            event.setState(EventSynchronization.SYN_DEVICE);
            event.setDeviceName(deviceName);
            mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_SYNCHRONIZATION).setValue(event));
        } else if ("00000000".equals(status)) {
            DeviceDaoUtil.getInstance().deleteByDeviceName(deviceName, deviceId);
            EventRefreshDevice event = new EventRefreshDevice();
            event.setDevice_id(deviceId);
            event.setDevice_type(device_type);
            event.setDeviceName(deviceName);
            event.setDevice_status(status);
            mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_REFRESH_DEVICE).setValue(event));
        } else {
            String device_room = content.substring(8);
            boolean isAlready = DeviceDaoUtil.getInstance().updateSubDevice(deviceName, deviceId, device_type, status, device_room);
            EventRefreshDevice event = new EventRefreshDevice();
            event.setType(isAlready ? 0 : 1);
            event.setDevice_id(deviceId);
            event.setDevice_type(device_type);
            event.setDeviceName(deviceName);
            event.setDevice_status(status);
            event.setRoomId(device_room);
            mHandler.post(() -> LiveDataBus.get().with(CommonId.KEY_EVENT_REFRESH_DEVICE).setValue(event));
            if (Arrays.asList(CellsEnum.SMART_BUTTON).contains(device_type)) {
                repairButton(deviceName, content, status);
            }
        }
    }

    //定时一秒把按键触发修改正常
    private void repairButton(String deviceName,String content, String status){
        if (status.substring(4,6).equals("01")){
            String new_status = status.substring(0, 4) + "AA" + status.substring(6);
            mHandler.postDelayed(()-> uploadDeviceStatus(deviceName, content, new_status), 1000);
        }
    }

    /**
     * 设备上报 同步设备名称/17帧
     * @param deviceName 网关
     * @param content data_str2
     * 返回NAME_OVER(结束帧)时候表示子设备名称同步完成
     */
    private void uploadDeviceName(String deviceName, String content){
        if ("NAME_OVER".equals(content)) {
            EventSynchronization event = new EventSynchronization();
            event.setState(EventSynchronization.SYN_FINISH);
            event.setDeviceName(deviceName);
            mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_SYNCHRONIZATION).setValue(event));
        } else {
            DeviceDaoUtil.getInstance().updateSubDeviceName(deviceName, content);
        }
    }

    /**
     * 设备上报 同步场景/26帧
     * @param deviceName 网关
     * @param content data_str1
     * @param content2 data_str2
     * 返回NULL时候表示网关无场景 需自动新增 在家离家睡眠
     */
    private void uploadSceneInfo(String deviceName, String content, String content2){
        int current = Integer.parseInt(content.substring(0,2), 16);
        if ("NULL".equals(content2)){
            SceneDaoUtil.getInstance().synchronizationScene(deviceName, content.substring(3));
        }else {
            SceneDaoUtil.getInstance().synchronizationScene(deviceName, current, content2);
        }
        SceneDaoUtil.getInstance().updateChoice(current, deviceName);
        EventSynchronization event = new EventSynchronization();
        event.setState(EventSynchronization.SYN_AUTO);
        event.setDeviceName(deviceName);
        mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_SYNCHRONIZATION).setValue(event));
    }

    /**
     * 设备上报 同步自动化/27帧
     * @param deviceName 网关
     * @param content1 data_str1
     * @param content2 data_str2
     * FFFF结束帧
     */
    private void uploadAutoInfo(String deviceName, String content1, String content2){
        if ("FFFF".equals(content1)){ //同步结束 删除无用自动化
            Log.i(TAG, "uploadAutoInfo: " + content2);
            CoderUtils.analysisFinalCode(deviceName, content2);
            return;
        }
        CoderUtils.analysisFullCode(content2, deviceName);
    }

    /**
     * 设备上报 切换当前场景/28帧
     * @param deviceName 网关
     * @param content 当前场景
     */
    private void uploadCurrentScene(String deviceName, String content) {
        int mSceneId = Integer.parseInt(content, 16);
        SceneDaoUtil.getInstance().updateChoice(mSceneId, deviceName);
        EventRefreshScene event = new EventRefreshScene();
        event.setDeviceName(deviceName);
        event.setSceneId(mSceneId);
        mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_REFRESH_SCENE).setValue(event));
    }

    /**
     * 设备上报 报警推送信息同步/45帧
     * @param deviceName 网关
     * @param page data_str1
     * @param content data_str2
     */
    private void uploadAlarmLogsInfo(String deviceName, String page, String content){
        if (content.length() > 30 && content.endsWith("OVER")) {
            if (content.length() % 30 == 4) {
                int mPage = Integer.parseInt(page, 16);
                List<WarnBean> list = CoderUtils.getWarnMsg(deviceName, content);
                EventRefreshLogs event = new EventRefreshLogs();
                event.setDeviceName(deviceName);
                event.setAlarmLogs(list);
                event.setIsOver(content.length()/30 >= 10 ? 0 : 1);
                event.setPage(mPage);
                mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_REFRESH_LOGS).setValue(event));
            }
        }else {
            EventRefreshLogs event = new EventRefreshLogs();
            event.setDeviceName(deviceName);
            event.setAlarmLogs(null);
            event.setIsOver(1);
            event.setPage(Integer.parseInt(page, 16));
            mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_REFRESH_LOGS).setValue(event));
        }
    }

    /**
     * 设备上报 同步子设备信息/48帧
     * @param deviceName 网关
     * @param page data_str1
     * @param content data_str2
     */
    private void uploadSubDeviceAlarmLogsInfo(String deviceName, String page, String content){
        if (content.length() > 0 && page.length() == 6) {
            if (content.length() % 24 == 4 && content.endsWith("OVER")) {
                List<HistoryBean> list = CoderUtils.getSubHistoryMsg(deviceName, content);
                EventRefreshSubLogs event = new EventRefreshSubLogs();
                event.setDeviceName(deviceName);
                event.setDeviceId(Integer.parseInt(page.substring(2, 6), 16));
                event.setIsOver(content.length() / 24 >= 10 ? 0 : 1);
                event.setPage(Integer.parseInt(page.substring(0, 2), 16));
                event.setList(list);
                mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_REFRESH_SUB_LOGS).setValue(event));
            } else if (content.endsWith("OVER")) {
                EventRefreshSubLogs event = new EventRefreshSubLogs();
                event.setDeviceName(deviceName);
                event.setDeviceId(Integer.parseInt(page.substring(2, 6), 16));
                event.setIsOver(1);
                event.setPage(Integer.parseInt(page.substring(0, 2), 16));
                event.setList(null);
                mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_REFRESH_SUB_LOGS).setValue(event));
            }
        }
    }

    /**
     * 处理报警信息
     * @param info 报警信息
     * @param deviceName 网关
     */
    private void onAlertPushInfo(String info, String deviceName){
        try {
            String type = info.substring(4,6);
            if("AC".equals(type)){
                int mid = Integer.parseInt(info.substring(6,10),16);
                doAliSceneAlertShow(mid,deviceName);
            }else if("AD".equals(type)) {
                int device_id = Integer.parseInt(info.substring(6,10),16);
                String device_status = info.substring(14,22);
                if(device_id == 0){
                    String status = DeviceStatusUtil.getGatewayAlert(mContext, device_status);
                    doAliGatewayAlertShow(status, deviceName);
                }else{
                    DeviceInfoBean subDevice = DeviceDaoUtil.getInstance().findByDeviceId(deviceName, device_id);
                    if (subDevice != null){
                        String device_type   = info.substring(10,14);
                        subDevice.setDevice_type(device_type);
                        subDevice.setDevice_status(device_status);
                        DeviceDaoUtil.getInstance().getDeviceDao().update(subDevice);
                        EventRefreshDevice event = new EventRefreshDevice();
                        event.setType(1);
                        event.setDevice_id(device_id);
                        event.setDevice_type(device_type);
                        event.setDeviceName(deviceName);
                        event.setDevice_status(device_status);
                        event.setRoomId(subDevice.getRoom_id());
                        mHandler.post(()-> LiveDataBus.get().with(CommonId.KEY_EVENT_REFRESH_DEVICE).setValue(event));
                        doAliAlertShow(subDevice);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 处理场景报警信息
     * @param mid 场景ID
     * @param deviceName 网关
     */
    private void doAliSceneAlertShow(int mid, String deviceName){
        try {
            String device_name = mContext.getString(R.string.ali_gateway);
            DeviceInfoBean myDeviceBean =  DeviceDaoUtil.getInstance().findGatewayByDeviceName(deviceName);
            if(myDeviceBean != null && !TextUtils.isEmpty(myDeviceBean.getNickName())){
                device_name =myDeviceBean.getNickName();
            }
            String mRecommendId = AutomationDaoUtil.getInstance().findDefaultByMid(mid, deviceName);
            String title;
            if(mRecommendId == null || "00".equals(mRecommendId)){
                String auto;
                AutomationBean mAuto = AutomationDaoUtil.getInstance().findAutomationByMid(mid, deviceName);
                if (mAuto!=null) {
                    List<DeviceInfoBean> mDeviceList = mAuto.getInputList();
                    if (mDeviceList!=null && mDeviceList.size() > 0) {
                        auto = mContext.getString(SmartDevice.getType(mDeviceList.get(0).getDevice_type()).getTypeStrId()) + "\t\t";
                    } else {
                        auto = mContext.getString(R.string.automation) + mid;
                    }
                }else {
                    auto = mContext.getString(R.string.automation) + mid;
                }
                title = String.format(mContext.getString(R.string.ali_gateway_scene_is_happen_has_scene), device_name+"\t\t", auto);
            }else{
                title = String.format(mContext.getString(R.string.ali_gateway_scene_is_happen_has_scene), device_name+"\t\t", mContext.getString(ConfigureUtil.getCommonName(mRecommendId)));
            }
            if (mCallBack!=null) mCallBack.showAlarmDialog(deviceName, title, true);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 处理网关报警信息
     * @param status 状态
     * @param deviceName 网关
     */
    private void doAliGatewayAlertShow(String status,String deviceName){
        String gateway = mContext.getString(R.string.ali_gateway);
        String room = mContext.getString(R.string.default_room);
        DeviceInfoBean mGateway = DeviceDaoUtil.getInstance().findGatewayByDeviceName(deviceName);
        if(mGateway != null){
            if (!TextUtils.isEmpty(mGateway.getNickName())){
                gateway = mGateway.getNickName();
            }
            if (mGateway.getOwned() != 1){
                room = mContext.getString(R.string.ali_gateway_share);
            }else {
                if (mGateway.getRoom_id()!=null){
                    RoomBean roomBean = RoomDaoUtil.getInstance().getRoomByRoomId(mGateway.getRoom_id());
                    if (roomBean.getNickname() != null){
                        room = roomBean.getNickname();
                    }else {
                        room = ConfigureUtil.roomName(mContext, roomBean.getRid());
                    }
                }
            }
        }
        String title = String.format(mContext.getString(R.string.ali_gateway_eq_is_happen_has_eq), room+"\t\t", gateway+"\t\t", status);
        if (mCallBack!=null) mCallBack.showAlarmDialog(deviceName, title, true);
    }

    /**
     * 处理子设备报警信息
     * @param subDevice 报警设备
     */
    private void doAliAlertShow(DeviceInfoBean subDevice){
        String room;
        String mSubDeviceName;
        String nickName = subDevice.getSubdeviceName();
        if(TextUtils.isEmpty(nickName)){
            mSubDeviceName = mContext.getString(SmartDevice.getType(subDevice.getDevice_type()).getTypeStrId())+subDevice.getDevice_ID();
        }else{
            mSubDeviceName = nickName;
        }
        DeviceInfoBean gateway = DeviceDaoUtil.getInstance().findGatewayByDeviceName(subDevice.getDeviceName());
        if (gateway.getOwned() != 1){
            room = mContext.getString(R.string.ali_gateway_share);
        }else {
            if (subDevice.getRoom_id()!=null){
                RoomBean roomBean = RoomDaoUtil.getInstance().getRoomByRoomId(subDevice.getRoom_id());
                if (roomBean.getNickname() != null){
                    room = roomBean.getNickname();
                }else {
                    room = ConfigureUtil.roomName(mContext, roomBean.getRid());
                }
            }else {
                room = mContext.getString(R.string.default_room);
            }
        }
        String ds = DeviceStatusUtil.getAlert(mContext, subDevice.getDevice_type(), subDevice.getDevice_status());
        String title = String.format(mContext.getString(R.string.ali_gateway_eq_is_happen_has_eq), room+"\t\t", mSubDeviceName + "\t\t", ds);
        boolean isAlarm = !mContext.getString(R.string.low_battery).equals(ds) && !mContext.getString(R.string.offline).equals(ds);
        if (mCallBack!=null) mCallBack.showAlarmDialog(subDevice.getDeviceName(), title, isAlarm);
    }

    private onAlarmCallBack mCallBack;

    public void onAlarmCallBack(onAlarmCallBack mCallBack) {
        this.mCallBack = mCallBack;
    }

    public interface onAlarmCallBack{
        void showAlarmDialog(String deviceName, String title, boolean isAlarm);
    }
}
